
#include <cppscript>

#define YYSTYPE var

#include "cppscript.tab.hpp"

struct parser_state
{
	void * scanner_state;
	var global_namespace;
	var current_function;
	var current_namespace;
	var current_block;

	var parse_result;
	parser_state();
	~parser_state();

	// Structure
	void declare_function(var decl);
	void define_function(var decl);
	void define_function_body(var block);
	void push_namespace(var name);
	void pop_namespace();
	void parse_complete();
	void push_block();
	var pop_block();
	void declare_library_function(var name, var fn);

	void declare_local_variable(var name);
	void declare_local_variable(var name, var init);
	void declare_default_local_variable(var name);

	// Expressions
	var literal_expression(var value);
	var id_expression(var name);
	var binary_expression(var fn, var lhs, var rhs);
	var evaluate(var expr);
	var throw_expression();
	var throw_expression(var ex);

	var lookup_variable(var block, var id);

	// Statements:
	void declaration_statement(var variable, var expr);
	void expression_statement(var expr);
	void block_statement(var block);

	// Errors:
	void error(const char * type, var description);
	void error_syntax_error();
	void error_too_many_arguments();
	void error_function_defined_twice();
	void error_function_inconsistent_return_type();
	void error_missing_script_main();
	void error_invalid_script_main();
	void error_duplicate_variable(var name);
	void error_not_evaluable();
	void error_not_callable();
	void error_not_assignable();
	void error_using_void_value();
	void error_unknown_identifier(var id);
};

// Types
var type_void();
var type_var();
var type_native();
var type_function();

/* Namespace:
namespace:
 	functions
	outer
	   name : map(arity, function)
	
function:
	return_type
	name
	arguments
	stack_pos
	eval : expression
	block : block
	functor

block:
	execute
	outer
	statements : array
	variables : map(name, stack_pos)

statement:

expression:
	eval: functor
*/


int yylex(var*scanner, parser_state & extra);
int yyerror(parser_state &,const void*);
int yyparse(parser_state & scanner);

var parse_file(var filename);
var parse_string(var string);

var create_namespace();
var create_function(var in_namespace, var name);
var create_arg(var name, var default_value);
var function_header(var ret, var name, var args);

var parse_integer(const var &);
var parse_string_token(const var & token);
var parse_double(const var & token);
var parse_char(const var & token);

var add(var a, var b);

